/* 
 *  Copyright (C) 2006 James Young
 * `gurumind(a)gmail.com
 * 
 * updated by Nick.xf 2010.01.12
 * change: UCS2String()
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

namespace IPDEditor
{
    class EncUtil
    {
        public static string AsciiString(byte[] data)
        {
            return Encoding.ASCII.GetString(data);
        }
        public static string UCS2String(byte [] data)
        {
            return Encoding.BigEndianUnicode.GetString(data);
        }

        public static string UTF8String(byte[] data)
        {
            return Encoding.UTF8.GetString(data);
        }
        public static string AddressBookUCS2String(byte[] data)
        {
            return AutoBin2String(data);
        }

        public static string AutoBin2String(byte[] data)
        {
            if (data == null || data.Length == 0)
                return null;

            string sRet = "";
            if(data[0] >= ' ')
                sRet = Encoding.ASCII.GetString(data);
            else
            {
                byte[] buff = new byte[data.Length - 1];
                for (int i = 0; i < data.Length - 1; i++)
                    buff[i] = data[i + 1];
                if ((byte)data[0] == 1)
                    sRet = Encoding.BigEndianUnicode.GetString(buff);
                else
                    sRet = Encoding.UTF8.GetString(buff);
            }

            char[] sep = { '\0' };
            return sRet.TrimEnd(sep);
        }

        public static byte[] AutoString2Bin(string s)
        {
            return AutoString2Bin(s, Encoding.UTF8, true);
        }

        public static bool IsAsciiOnly(string s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] < ' ' || s[i] > '~')
                {
                    return false;
                }
            }
            return true;
        }

        //will add the trilling '\0'
        public static byte [] AutoString2Bin(string s, Encoding enc, bool NullTerm)
        {
            //test if have non-ascii
            if (IsAsciiOnly(s))
            {
                byte [] data = Encoding.ASCII.GetBytes(s);
                int pad = 0;
                if (NullTerm)
                    pad = 1;
                byte[] data2 = new byte[data.Length + pad];
                for (int i = 0; i < data.Length; i++)
                    data2[i] = data[i];
                if(NullTerm)
                    data2[data.Length] = 0;
                return data2;
            }
            else
            {
                byte[] buff = enc.GetBytes(s);
                byte[] buff2 = new byte[buff.Length + 1];
                if (enc.EncodingName == Encoding.BigEndianUnicode.EncodingName)
                    buff2[0] = 1;
                else
                    buff2[0] = 0;
                for (int i = 0; i < buff.Length; i++)
                    buff2[i + 1] = buff[i];
                //buff2[buff2.Length - 1] = 0;
                return buff2;
            }
        }

        public static int BIN2Int(byte[] data)
        {
            if (data.Length == 1)
            {
                return (int)data[0];
            }
            int n = (int)data[0] + (int)(data[1] << 8) + (int)(data[2] << 16) + (int)(data[3] << 24);
            return n;
        }

        public static string BIN2HexString(byte[] data)
        {
            int n = (int)data[0] + (int)(data[1] << 8) + (int)(data[2] << 16) + (int)(data[3] << 24);
            return string.Format("0x{0:X8}", n);
        }

        public static string BIN2AsciiOnly(byte[] data)
        {
            return BIN2Ascii(data, '\0');
        }

        public static string BIN2Ascii(byte[] data)
        {
            return BIN2Ascii(data, '.');
        }

        public static long BIN2Long(byte[] data)
        {
            long x = 0;
            for (int i = 0; i < 8; i++)
                x += ((long)data[i]) << (i * 8);
            return x;
        }
        public static string UnEscape(string escString)
        {
            return System.Web.HttpUtility.UrlDecode(escString, Encoding.UTF8);
        }

        public static byte[] Number2Bin(object number)
        {
            if (number is int)
            {
                byte[] data = new byte[4];
                int d = (int)number;
                data[0] = (byte)(d & 0x000000FF);
                data[1] = (byte)((d & 0x0000FF00) >> 8);
                data[2] = (byte)((d & 0x00FF0000) >> 16);
                data[3] = (byte)((d & 0xFF000000) >> 24);
                return data;
            }
            else if (number is short)
            {
                byte[] data = new byte[2];
                short d = (short)number;
                data[0] = (byte)(d & 0xFF);
                data[1] = (byte)((d & 0xFF00) >> 8);
                return data;
            }
            else if (number is byte)
            {
                byte[] data = new byte[1];
                byte d = (byte)number;
                data[0] = d;
                return data;
            }
            return null;
        }

        public static string BIN2Ascii(byte[] data, char blank)
        {
            byte[] buff = new byte[data.Length];
            int j = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (data[i] >= ' ' && data[i] <= '~')
                    buff[j++] = data[i];
                else
                {
                    if (blank == '\0')
                        continue;
                    else
                    {
                        buff[j++] = (byte)blank;
                    }
                }
            }

            return Encoding.ASCII.GetString(buff);
        }

        public static string Bin2RichFormat(byte[] binData, long offset)
        {
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < binData.Length; j += 16)
            {
                sb.AppendFormat("{0:x6}  ", offset + j);

                int k = j;
                for (; k < j + 16 && k < binData.Length; k++)
                    sb.AppendFormat("{0:x2} ", binData[k]);
                for (; k < j + 16; k++)
                    sb.Append("   ");

                sb.Append("   ");
                for (k = j; k < j + 16 && k < binData.Length; k++)
                {
                    if (binData[k] >= ' ' && binData[k] <= '~')
                        sb.AppendFormat("{0}", (char)binData[k]);
                    else
                        sb.AppendFormat(".");
                }
                sb.AppendFormat("\n");
            }
            return sb.ToString();
        }

        public static int String2Int(string text)
        {
            string numStr = text.Trim().ToLower();
            if (numStr.StartsWith("0x"))
                return int.Parse(numStr.Replace("0x", ""), NumberStyles.HexNumber);
            else
                return int.Parse(numStr, NumberStyles.Integer);
        }
    }
}
